import 'package:dio/dio.dart';
import 'package:elevator/dio/result_data.dart';
import 'package:flutter/material.dart';

import '../utils/utils_dialog.dart';
import '../utils/utils_logger.dart';
import 'code.dart';
import 'interceptors/error_interceptor.dart';
import 'interceptors/header_interceptor.dart';
import 'interceptors/log_interceptor.dart';
import 'interceptors/response_interceptor.dart';

///http请求
class HttpManager {
  static const typeJson = "application/json";
  static const typeForm = "application/x-www-form-urlencoded";

  final Dio _dio = Dio(); // 使用默认配置

  HttpManager() {
    _dio.interceptors.add(HeaderInterceptors());

    _dio.interceptors.add(LogsInterceptors());

    _dio.interceptors.add(ErrorInterceptors());

    _dio.interceptors.add(ResponseInterceptors());
  }

  ///发起网络请求,默认是post请求
  ///[ url] 请求url
  ///[ params] 请求参数
  ///[ header] 外加头
  ///[ option] 配置
  Future<ResultData> netFetch(
    url, {
    params,
    BuildContext? context,
    noTip = false,
    Options? option,
    Map<String, dynamic> headers = const {
      "Accept": "application/json",
      "Content-Type": "application/json; charset=UTF-8",
    },
  }) async {
    option ??= Options(method: 'post');
    option.headers = headers;

    if (context != null) {
      UtilsDialog.showLoadingDialog(context);
    }
    Response response;
    try {
      response = await _dio.request(url, data: params, options: option);
    } on DioException catch (e) {
      return resultError(e, url: url);
    } finally {
      if (null != context) {
        Navigator.pop(context);
      }
    }
    if (response.data is DioException) {
      return resultError(response.data, url: url);
    }
    return response.data;
  }

  resultError(DioException e, {required String url, bool noTip = false}) {
    Response errorResponse =
        Response(statusCode: 666, requestOptions: RequestOptions(path: url));
    if (e.response != null) {
      errorResponse = e.response!;
    }
    if (e.type == DioExceptionType.connectionTimeout ||
        e.type == DioExceptionType.receiveTimeout) {
      errorResponse.statusCode = Code.networkTimeout;
    }
    return ResultData(
        Code.errorHandleFunction(errorResponse.statusCode, e.message, noTip),
        false,
        errorResponse.statusCode);
  }

  /// formData
  /// [
  Future<ResultData> uploadSingleFile({
    required String url,
    required String filePath,
    required String fileName,
    required Function(double)? onProgress,
    Options? option,
    Map<String, dynamic> headers = const {
      "Accept": "application/json",
      "Content-Type": "application/json; charset=UTF-8",
    },
  }) async {
    logd("上传文件地址:$filePath");

    FormData formData = FormData.fromMap(
        {"file": MultipartFile.fromFileSync(filePath, filename: fileName)});
    option ??= Options(method: 'post');

    option.headers = headers;
    Response response;
    try {
      response = await _dio.post(
        url,
        options: option,
        data: formData,
        onSendProgress: (count, total) {
          logd("===============上传进度:  current:$count total:$total");
          onProgress?.call(count / total);
        },
      );
      if (null != response.data) {
        ResultData resultData = response.data;
        logd(
            "===============请求完成 resultData.code: ${resultData.code}   response.data: ${response.data}");
        return resultData;
      }
    } on DioException catch (err) {
      logd("===============请求完成 error: $err   ");
      return resultError(err, url: url);
    }
    if (response.data is DioException) {
      return resultError(response.data, url: url);
    }
    return response.data;
  }

  /// formData
  Future<bool> uploadMultipleFile({
    required String url,
    required List<String> filesPath,
    required String fileName,
    required Function(double)? onProgress,
    required FormData formData,
    Options? option,
    Map<String, dynamic> headers = const {
      "Accept": "application/json",
      "Content-Type": "application/json; charset=UTF-8",
    },
  }) async {
    logd("上传文件地址:$filesPath");
    option ??= Options(method: 'post');
    option.headers = headers;

    List<MultipartFile> multipleFile = [];
    for (var path in filesPath) {
      multipleFile.add(MultipartFile.fromFileSync(path, filename: fileName));
    }

    try {
      var response = await _dio.post(
        url,
        options: option,
        data: formData,
        onSendProgress: (count, total) {
          logd("===============上传进度:  current:$count total:$total");
          onProgress?.call(count / total);
        },
      );
      if (null != response.data) {
        ResultData resultData = response.data;
        if (resultData.code == 0) {
          return true;
        }
        logd(
            "===============请求完成 resultData.code: ${resultData.code}   response.data: ${response.data}");
      }
    } on DioException catch (err) {
      logd("===============请求完成 error: $err   ");
    }
    return false;
  }
}

final HttpManager httpManager = HttpManager();
